package com.apes.fn.scm.internal.help.service.voucher.sale;

import com.apes.fn.mdm.paint.PaintBusinessScope;
import com.apes.fn.mdm.paint.PaintBusinessScopeRepository;
import com.apes.fn.scm.internal.help.model.InternalHelpReturnApproval;
import com.apes.fn.scm.internal.help.model.InternalHelpReturnApprovalItem;
import com.apes.fn.server.servicePlan.model.ServicePlan;
import com.apes.framework.api.DomainService;
import com.apes.framework.jpa.spec.JpaDsl;
import com.apes.framework.util.MapUtil;
import com.apes.framework.util.ReflectUtil;
import com.apes.scm.account.account.model.InventoryBatch;
import com.apes.scm.account.account.service.InventoryService;
import com.apes.scm.contract.model.Contract;
import com.apes.scm.contract.service.ContractService;
import com.apes.scm.masterdata.party.model.PartyRole;
import com.apes.scm.sal.saleOrder.SaleOrder;
import com.apes.scm.sal.saleOrder.SaleOrderItem;
import com.apes.scm.voucher.model.Voucher;
import com.apes.scm.voucher.model.VoucherInventory;
import com.apes.scm.voucher.model.VoucherItem;
import com.apes.scm.voucher.repository.VoucherInventoryRepository;
import com.apes.scm.voucher.repository.VoucherRepository;
import com.apes.scm.voucher.service.BusinessType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 油漆商品退货
 *
 * @Author wuq
 * @Date 2021-10-19
 */
@Service
public class SalePaintReturnVoucherService extends DomainService {

    @Autowired
    private ContractService contractService;
    @Autowired
    private VoucherInventoryRepository voucherInventoryRepository;
    @Autowired
    private VoucherRepository voucherRepository;
    @Autowired
    private InventoryService inventoryService;
    @Autowired
    private PaintBusinessScopeRepository paintBusinessScopeRepository;


    public void process(Map<SaleOrderItem, InternalHelpReturnApprovalItem> param) {
        SaleOrderItem saleOrderItem = param.entrySet().iterator().next().getKey();
        SaleOrder saleOrder = saleOrderItem.getSaleOrder();

        // 查询喷漆经营范围，判断是否为对账公司
        List<PaintBusinessScope> paintBusinessScopes = paintBusinessScopeRepository.findByDept(saleOrder.getDept().getId());
        PartyRole paintCompany = paintBusinessScopes.get(0).getCompany();       // 油漆对账公司
        PartyRole supplier = paintBusinessScopes.get(0).getSupplier();          // 油漆供应商

        // 找到之前的销售凭证
        Voucher originSaleVoucher = voucherRepository.findOne(
                JpaDsl.toCriteriaByEq("sourceBusinessType", SaleOrder.class.getSimpleName(), "source", saleOrder.getId(),
                        "originBusinessType", ServicePlan.class.getSimpleName(),
                        "origin", saleOrder.getOrigin(), "voucherType", "CUSTOMER_SALE"))
                .orElseThrow(() -> new RuntimeException("生成内协油漆返厂凭证时，未找到：" + saleOrder.getId() + " 的业务凭证！"));

        // 判断是否为跨公司
        if (saleOrder.getCompany().getId().equals(paintCompany.getId())){
            // 同公司退货
            returnPurchase(supplier, originSaleVoucher, param);
        } else {
            // 退油漆给对账公司
            returnPurchase(paintCompany, originSaleVoucher, param);

            // 跨公司退货
            returnCrossPaintVoucher(paintCompany, supplier, saleOrderItem, param);
        }
    }

    private void returnCrossPaintVoucher(PartyRole paintCompany, PartyRole supplier, SaleOrderItem saleOrderItem,
                                         Map<SaleOrderItem, InternalHelpReturnApprovalItem> param){
        List<InternalHelpReturnApprovalItem> returnItems = new ArrayList<>(param.values());
        // 第一步：退对基地的销售
        PartyRole partner = saleOrderItem.getSaleOrder().getCompany().getParty().getPartyRoleByType("Customer");
        String originItemId = saleOrderItem.getId();
        Voucher originSaleVoucher = voucherRepository.findSaleVoucherByCompanyAndItemOrigin(paintCompany, partner, originItemId);
        Optional.ofNullable(originSaleVoucher).orElseThrow( () -> new RuntimeException("跨公司油漆退回时，没有找到施工方的销售凭证"));
        returnSaleVoucher(originSaleVoucher, returnItems);

        // 第二步：退对油漆供应商的采购
        returnPurchase(supplier, originSaleVoucher, param);
    }

    private void returnPurchase(PartyRole supplier,  Voucher originSaleVoucher, Map<SaleOrderItem, InternalHelpReturnApprovalItem> param) {
        List<InternalHelpReturnApprovalItem> internalHelpReturnApprovalItems = new ArrayList<>(param.values());
        InternalHelpReturnApproval internalHelpReturnApproval = internalHelpReturnApprovalItems.get(0).getApproval();

        Voucher voucher = new Voucher();
        voucher.setReturned(true);
        voucher.setBusinessType(BusinessType.PURCHASE_RETURN);

        voucher.setDept(originSaleVoucher.getDept());
        voucher.setCompany(originSaleVoucher.getCompany());
        voucher.setPartner(supplier.getParty().getPartyRoleByType("Supplier"));
        voucher.setClerk(internalHelpReturnApproval.getApplyUid());

        // 通过批次获取部门
        Contract contract = contractService.getContract(voucher.getDept(), voucher.getPartner(), "distribution", "supplier", "分销单油漆退回业务");
        voucher.setContract(contract);
        voucher.setInventoryMode(contract.getCooperation().getInventoryMode());
        voucher.setAccountingMethod(contract.getCooperation().getAccountingMethod());

        voucher.setScene(internalHelpReturnApproval.getScene());
        voucher.setOrigin(internalHelpReturnApproval.getOrigin());
        voucher.setOriginBusinessType(internalHelpReturnApproval.getOriginBusinessType());
        voucher.setSource(internalHelpReturnApproval.getId());
        voucher.setSourceBusinessType(internalHelpReturnApproval.getInnerBusinessType());
        voucher.setCustomerExpand(internalHelpReturnApproval.getCustomerExpand().getId());

        voucher.setVoucherItems(
                internalHelpReturnApprovalItems.stream().map(
                        item -> {
                            VoucherItem voucherItem = new VoucherItem();

                            voucherItem.setProduct(item.getProduct());
                            voucherItem.setUom(item.getUom());
                            voucherItem.setProductQty(-1.00 * item.getProductReturnQty());
                            voucherItem.setOriginItemId(String.valueOf(item.getId()));
                            voucherItem.setSourceItemId(String.valueOf(item.getId()));
                            voucherItem.setOwner(originSaleVoucher.getCompany());

                            // 找到原销售凭证的明细行
                            VoucherItem saleVoucherItem = originSaleVoucher.getVoucherItems().stream()
                                    .filter( saleItem -> saleItem.getProduct().getId().equals(item.getProduct().getId()) )
                                    .findFirst()
                                    .orElseThrow(() -> new RuntimeException("生成内协油漆返厂凭证时，根据商品编码没有找到对应的凭证明细，" +
                                            "商品编码："+ item.getProduct().getId() +"，凭证编码："+ originSaleVoucher.getId()));

                            // 获取原销售批次
                            VoucherInventory voucherInventory = voucherInventoryRepository.findAll(
                                    JpaDsl.toCriteriaByEq("voucher.id", originSaleVoucher.getId(), "voucherItem", saleVoucherItem))
                                    .stream().findFirst().get();

                            InventoryBatch inventoryBatch = voucherInventory.getInventoryBatch();
                            voucherItem.setInventoryBatch(inventoryBatch);
                            voucherItem.setPriceUnit(inventoryBatch.getTaxCostPrice());
                            voucherItem.setSupplier(inventoryBatch.getSupplier());
                            voucherItem.setTax(inventoryBatch.getTax());

                            //  增加（减少）冻结数量
                            inventoryService.changeFrostQty(voucherItem.getInventoryBatch(), item.getUom(), item.getProductReturnQty(), inventoryBatch.getCompany(),
                                    internalHelpReturnApproval.getInnerBusinessType(), internalHelpReturnApproval.getId(), item.getId(), "门店经销带安返厂凭证");

                            return voucherItem;
                        }).collect(Collectors.toSet()));

        voucher = invoke("voucher.create", MapUtil.mapped(voucher));
        invoke("invoice.create", MapUtil.mapped(invoke("voucher.flow.invoice", MapUtil.mapped(voucher))));
    }

    private void returnSaleVoucher(Voucher originSaleVoucher, List<InternalHelpReturnApprovalItem> returnItems){
        InternalHelpReturnApproval internalHelpReturnApproval = returnItems.get(0).getApproval();

        Voucher voucher = new Voucher();
        // 销售退回必填字段
        voucher.setReturned(true);
        voucher.setBusinessType(BusinessType.SALE_RETURN);
        voucher.setVoucher(originSaleVoucher);

        ReflectUtil.copy(originSaleVoucher, voucher, "dept", "company", "partner", "contract");
        voucher.setInventoryMode(voucher.getContract().getCooperation().getInventoryMode());     //设置库存模式
        voucher.setAccountingMethod(voucher.getContract().getCooperation().getAccountingMethod());  // 核算方式

        voucher.setCustomerExpand(internalHelpReturnApproval.getCustomerExpand().getId());
        voucher.setScene(internalHelpReturnApproval.getScene());
        voucher.setOrigin(internalHelpReturnApproval.getOrigin());
        voucher.setOriginBusinessType(internalHelpReturnApproval.getOriginBusinessType());
        voucher.setSource(internalHelpReturnApproval.getId());
        voucher.setSourceBusinessType(internalHelpReturnApproval.getInnerBusinessType());

        voucher.setVoucherItems(
                originSaleVoucher.getVoucherItems().stream().map(saleItem -> {
                    VoucherItem voucherItem = new VoucherItem();

                    returnItems.stream()
                            .filter(returnItem -> returnItem.getProduct().getId().equals(saleItem.getProduct().getId()))
                            .forEach(retailReturnItem -> {

                                voucherItem.setProduct(saleItem.getProduct());
                                voucherItem.setTax(saleItem.getTax());

                                voucherItem.setUom(saleItem.getUom());          // 设置为销售的单位以及数量
                                voucherItem.setProductQty(-1 * Math.abs(saleItem.getProductQty()));
                                voucherItem.setPriceUnit(saleItem.getPriceUnit());      // 默认为退货单价
                                voucherItem.setOwner(originSaleVoucher.getCompany());

                                voucherItem.setOriginItemId(retailReturnItem.getId());
                                voucherItem.setSourceItemId(retailReturnItem.getId());
                                voucherItem.setVoucherItem(saleItem);   // 退回时传入明细行号
                            });

                    return voucherItem;
                }).filter(voucherItem -> voucherItem.getProduct() != null).collect(Collectors.toSet()));

        voucher = invoke("voucher.create", MapUtil.mapped(voucher));
        invoke("invoice.create", MapUtil.mapped(invoke("voucher.flow.invoice", MapUtil.mapped(voucher))));
    }
}
